#include "dpdk_ring.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <netinet/ip.h>
#include <netinet/udp.h>

#define NB_MBUFS 64*1024 /* use 64k mbufs */
#define MBUF_CACHE_SIZE 256
#define PKT_BURST 32
#define RX_RING_SIZE 512
#define TX_RING_SIZE 128

int g_portid;

static void display(const unsigned char* buf, int len)
{
	int i;
	for ( i = 0; i < len; i++ )
	{
		printf("%02x ", buf[i]);
		if( (i+1) % 16 == 0)
		{
			printf("\n");
			continue;
		}

		if( (i+1) % 8 == 0)
			printf(" ");
	}
	printf("\n");
}


static int pkt_process(uint8_t* pkt, int len, void* arg)
{
	static int rx_cnt;

	rx_cnt++;
	display(pkt, len);

	arg = NULL;

#define DATA_LEN 20

	if(rx_cnt % 10 == 0)
	{
		uint8_t buf[512];
		int pkt_size = 14 + sizeof(struct iphdr)  + sizeof(struct udphdr) + DATA_LEN;
		memcpy(buf, "\x00\x17\x17\x17\x17\x17", 6);
		memcpy(buf + 6, "\x00\x16\x16\x16\x16\x16", 6);
		memcpy(buf + 12, "\x08\x00", 2);

		struct iphdr *iph = (struct iphdr *)(buf + 14);
		iph->ihl = 0x5;
		iph->version = 0x4;
		iph->tos = 0;
		iph->tot_len = htons(pkt_size - 14);
		iph->id = 0x1122;
		iph->frag_off = 0;
		iph->ttl = 0x80;
		iph->protocol = 0x11;
		iph->check = 0x92fa;
		iph->saddr = 0x01020304;
		iph->daddr = 0x0a0b0c0d;


		struct udphdr* uh = (struct udphdr *)((char*)iph + sizeof(struct iphdr));
		uh->source = htons(80);
		uh->dest = htons(9818);
		uh->len = htons(DATA_LEN + 8);
		uh->check = 0xc911;

		char* data = (char*)uh + sizeof(struct udphdr);
		snprintf(data, DATA_LEN, "message %d from dpdk", rx_cnt), 

		dpdk_send(g_portid, buf, pkt_size);
	}

	return 0;
}

int main(int argc, char** argv)
{
	if(argc < 2)
	{
		printf("Usage: %s portid\n", argv[0]);
		return 0;
	}

	g_portid = atoi(argv[1]);

	dpdk_init(g_portid, pkt_process, NULL, 
              NB_MBUFS, MBUF_CACHE_SIZE, RX_RING_SIZE, TX_RING_SIZE);

	return 0;

}


